﻿//*****************************************************************************
//
//  Copyright 2008 IT Cloud Company
//
//  This software is available under the Microsoft Public License.  Please
//  read the license agreement at http://opensource.org/licenses/ms-pl.html
//  before using the software.
//
//  Authors:
//    Don Song (don@itcloud.com)
//
//*****************************************************************************

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;

namespace HeadLinx.AD.Common
{
    public static class Utility
    {
        /// <summary>
        /// Converts array of bytes to hexBinary encoded string format.
        /// </summary>
        /// <param name="data">Byte array to convert.</param>
        /// <returns>hexBinary encoded string.</returns>
        public static string ToHexBinary(byte[] data)
        {
            using (MemoryStream memStream = new MemoryStream(data, false))
            {
                return ToHexBinary(memStream, false);
            }
        }

        /// <summary>
        /// Converts array of bytes to hexBinary encoded string format.
        /// </summary>
        /// <param name="data">Byte array to convert.</param>
        /// <param name="insertSpaces">If true, inserts a space between each hex encoded byte.</param>
        /// <returns>hexBinary encoded string.</returns>
        public static string ToHexBinary(byte[] data, bool insertSpaces)
        {
            using (MemoryStream memStream = new MemoryStream(data, false))
            {
                return ToHexBinary(memStream, insertSpaces);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputBinaryStream"></param>
        /// <returns></returns>
        public static string ToHexBinary(Stream inputBinaryStream)
        {
            return ToHexBinary(inputBinaryStream, false);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputBinaryStream"></param>
        /// <param name="insertSpaces">If true, will insert spaces.</param>
        /// <returns></returns>
        public static string ToHexBinary(Stream inputBinaryStream, bool insertSpaces)
        {
            if (inputBinaryStream.Length > int.MaxValue)
            {
                throw new ArgumentException("Stream is too large to convert to hexBinary.");
            }

            // Truncate long to int, this is OK because we prohibit longer streams above.
            int streamLen = (int)inputBinaryStream.Length;

            // Set initial buffer size for efficiency sake (will still work if not perfectly accurate).
            int outputStringLen = streamLen * 2;
            if (insertSpaces)
            {
                outputStringLen += streamLen; // add extra buffer for spaces
            }

            StringBuilder hex = new StringBuilder(outputStringLen);

            int b = 0;
            int idx = 0;
            while ((b = inputBinaryStream.ReadByte()) != -1)
            {
                hex.AppendFormat("{0:x2}", b);

                if (insertSpaces && (idx < streamLen - 1))
                {
                    hex.Append(" ");
                }

                idx++;
            }

            return hex.ToString();
        }

        /// <summary>
        /// Converts a hexBinary string into an array of bytes.
        /// </summary>
        /// <param name="hex">hexBinary string encoded data to convert.</param>
        /// <returns>Byte array.</returns>
        public static byte[] FromHexBinary(string hex)
        {
            if (hex.IndexOf(' ') != -1)
            {
                // Remove embedded strings.
                hex = hex.Replace(" ", "");
            }

            if ((hex.Length % 2) != 0)
            {
                throw new InvalidDataException("Invalid hexBinary string.");
            }

            byte[] data = new byte[hex.Length / 2];

            for (int i = 0; i < hex.Length; i += 2)
            {
                data[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }

            return data;
        }

        public static byte[] ExtractEmbeddedAssemblyResources(Assembly a, string desiredResName)
        {
            foreach (string resName in a.GetManifestResourceNames())
            {
                if (String.Compare(resName, desiredResName, true) == 0)
                {
                    ManifestResourceInfo resInfo = a.GetManifestResourceInfo(resName);
                    if (resInfo.ResourceLocation == ResourceLocation.Embedded)
                    {
                        using (Stream inputStream = a.GetManifestResourceStream(resName))
                        {
                            using (BinaryReader reader = new BinaryReader(inputStream))
                            {
                                return reader.ReadBytes((int)inputStream.Length);
                            }
                        }
                    }
                }
            }

            return null;
        }

    }
}
